import { runQueue } from "../util/async";

// 包括 hash model 和 html5 model 都有的逻辑
export default class HistoryBase {
  constructor(router) {
    this.router = router;
    this.routerTable = router.routerTable; // 依赖反转,将routerTable注入进来
  }

  // 修改route的时机
  listen(cb) {
    this.cb = cb;
  }

  // 跳转对应的路由
  transitionTo(target) {
    // 判断 target 是否在路由表中
    const route = this.routerTable.match(target);

    // 当 路由守卫前置执行完成后, 执行更新路由,在render, 再触发全局 afterEach
    this.confirmTransition(route, () => {
      this.updateRoute(route);
    });
  }

  confirmTransition(route, onComplete, onAbort) {
    if (route === this.current) {
      return;
    }

    // 页面初始化路由任务队列 -- 执行路由守卫
    const queue = [
      ...this.router.beforeHooks, // 先执行全局 beforeEach
      route.beforeEnter, // 路由独享守卫 route.beforeEnter
      route.component.beforeRouteEnter.bind(route.instance), // 组件路由 beforeRouteEnter 注意this的指向
      ...this.router.resolveHooks // 执行全局 beforeResolve
    ];

    const iterator = (hook, next) => {
      // hook (to, from, next)
      hook(route, this.current, to => {
        if (to === false) {
          // 判断中断信息是否存在
          onAbort && onAbort(to);
        } else {
          next(to);
        }
      });
    };

    runQueue(queue, iterator, () => onComplete());
  }

  updateRoute(route) {
    const from = this.current;
    this.current = route;
    this.cb(this.current);

    // 全局 afterEach 在 更新后执行的
    this.router.afterHooks.forEach(hook => {
      hook && hook(route, from);
    });
  }
}
